﻿@using Microsoft.Extensions.Logging
@using System.Reactive.Subjects
@using System.Reactive.Linq
@if (IsAdding)
{
    <AutoComplete Options="Options" OnSelectionChange="OnCreatingTag">
        <ChildContent>
            <AutoCompleteSearch OnPressEnter="e => OnCreatingTag(default)"
                                OnBlur="e => OnCreatingTag(default)"
                                Placeholder="enter to add tag"
                                @ref="ValueRef"
                                @bind-Value="_value">
            </AutoCompleteSearch>
        </ChildContent>
    </AutoComplete>
}
else
{
    <Tag Class="site-tag-plus" OnClick="e => OnClickAddTagAsync()">
        <Icon Type="plus"/>New Tag
    </Tag>
}

@code {

    public record NewTagArgs(string[] Tags);

    [Inject]
    public ILogger<TagInput> Logger { get; set; }

    private AutoCompleteSearch ValueRef = null!;

    [Parameter]
    public bool IsAdding { get; set; }

    private string _value = null!;

    [Parameter]
    public EventCallback<NewTagArgs> OnNewTagsCreated { get; set; }

    [Parameter]
    public string Separator { get; set; } = ",";

    [Parameter]
    public string[] Options { get; set; } = Array.Empty<string>();

    private readonly Subject<string> _newValueSubject = new();

    protected override async Task OnInitializedAsync()
    {
        await base.OnInitializedAsync();
        _newValueSubject
            .DistinctUntilChanged()
            .Buffer(TimeSpan.FromMilliseconds(10), 10)
            .Where(x => x.Count > 0)
            .Select(x => x.FirstOrDefault(s => !string.IsNullOrWhiteSpace(s)))
            .Subscribe(async value =>
            {
                var created = await FireCreateTagAsync(value);
                if (created)
                {
                    IsAdding = true;
                    _value = string.Empty;
                    await ValueRef.Ref.FocusAsync();
                }
                else
                {
                    IsAdding = false;
                }
                StateHasChanged();
            });
    }

    private void OnClickAddTagAsync()
    {
        IsAdding = true;
        Task.Run(async () =>
        {
            await Task.Delay(TimeSpan.FromMilliseconds(100));
            await ValueRef.Ref.FocusAsync();
        });
    }

    private void OnCreatingTag(AutoCompleteOption? option)
    {
        _newValueSubject.OnNext(option?.Value?.ToString() ?? _value);
    }

    private async Task<bool> FireCreateTagAsync(string? value)
    {
        string[] newTags = Array.Empty<string>();
        if (!string.IsNullOrWhiteSpace(value))
        {
            newTags = value.Split(Separator)
                .Select(x => x.Trim())
                .Where(x => !string.IsNullOrWhiteSpace(x))
                .ToArray();
        }

        if (newTags.Any())
        {
            await OnNewTagsCreated.InvokeAsync(new NewTagArgs(newTags));
            return true;
        }

        return false;
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        await base.OnAfterRenderAsync(firstRender);
        if (firstRender && IsAdding)
        {
            await ValueRef.Focus();
        }
    }

}